#include "rational.h"

Rational::Rational(int i, int j)
{
	int m = i;
	int n = j;
	int div;
	if ((m < 0)&&(n < 0)) 
	{
		m = -m; 
		n = -n;
		div = binEuclidean(m, n);
	}
	else if (m < 0) 
		div = binEuclidean(-m, n);
	
	else if (n < 0) 
		div = binEuclidean(m, -n);

	else
		div = binEuclidean(m, n);

	//int 

	if (div == 0)
	{
		numerator = 0;
		denominator = 0;
	}

	else
	{
		numerator = m / div;
		denominator = n / div;
	}
}

Rational::Rational(int k)
{
	

}

double Rational::getDouble(const Rational& r)
{
    return (double) r.numerator / (double) r.denominator;
}

int Rational::binEuclidean(int m, int n) const
{
	//cout << m << " "  << n << endl;

	if (n == 0) {return m;}
	if (m == 0) {return n;}
	if (n == m) {return m;}	
	if (m == 1) {return 1;}
	if (n == 1) {return 1;}
	

	if ((m % 2 == 0) && (n % 2 == 0))
	{
		//cout << res << endl;
		//res = binEuclidean(m>>1,n>>1,res) << 1;
		return binEuclidean(m>>1,n>>1) << 1;
		
	}

	else if ((m % 2 == 0) && (n % 2 != 0))
	{
		return binEuclidean(m>>1,n);
	}

	else if ((m % 2 != 0) && (n % 2 == 0))
	{
		return binEuclidean(m,n>>1);
	}

	else if ((m % 2 != 0) && (n % 2 != 0))
	{
		if (n > m)
		{
			return binEuclidean((n - m) >> 1,m);
		}

		else
		{
			return binEuclidean((m - n) >> 1,n);
		}
	}


}

Rational Rational::reduce(const Rational &r) const
{
	
	int m = r.getNumerator();
	int n = r.getDenominator();

	int div = 1;
	if ((m < 0)&&(n < 0)) 
	{
		m = -m; 
		n = -n;
		div = binEuclidean(m, n);
	}
	else if (m < 0) 
		div = binEuclidean(-m, n);
	
	else if (n < 0) 
		div = binEuclidean(m, -n);
	else 
	{
		div = binEuclidean(m, n);
	}

	if (div == 0)
	{
		return	Rational(0, 0);
	}
	
	
	//cout << div << endl;
	return	Rational((m / div), (n / div));
}

Rational Rational::operator+(const Rational& r) const
{
	int n1 = this->getNumerator() * r.getDenominator();
	int n2 = r.getNumerator() * this->getDenominator();
	int d = this->getDenominator() * r.getDenominator();
	
	return reduce( Rational(n1 + n2 , d) );
}
Rational Rational::operator-(const Rational& r) const
{

	int n1 = this->getNumerator() * r.getDenominator();
	int n2 = r.getNumerator() * this->getDenominator();
	int d = this->getDenominator() * r.getDenominator();
	return reduce( Rational(n1 - n2 , d) );

}
Rational Rational::operator*(const Rational& r) const
{	
	return reduce( Rational(this->getNumerator() * r.getNumerator(), 
			this->getDenominator() * r.getDenominator()) );

}
Rational Rational::operator/(const Rational& r) const
{	
	return reduce( Rational(this->getNumerator() / r.getNumerator(), 
			this->getDenominator() / r.getDenominator()) );

}
bool Rational::operator==(const Rational &r2) 
{
	if ((this->getNumerator() == r2.getNumerator()) &&
	 (this->getDenominator() == r2.getDenominator())) 
	 {
	 	return true;
	}
	return false;
}

bool Rational::operator!=(const Rational &r2) 
{
	if ((this->getNumerator() != r2.getNumerator()) ||
	 (this->getDenominator() != r2.getDenominator())) 
	 {
	 	return true;
	}
	return false;
}

bool Rational::operator>(const Rational &r2) 
{
	
	//(r1 - r2).print();
	if (getDouble(*this - r2) > 0) 
	{
		return true;
	}

	return false;
}

bool Rational::operator>=(const Rational &r2) 
{
	
	//(r1 - r2).print();
	if (getDouble(*this - r2) >= 0) 
	{
		return true;
	}

	return false;
}

bool Rational::operator<(const Rational &r2) 
{

	//r1.print();
	//r2.print();
	//(r1 - r2).print();

	if (getDouble(*this - r2) < 0) 
	{
		return true;
	}

	return false;	
}
bool Rational::operator<=(const Rational &r2) 
{
	if (getDouble(*this - r2) <= 0) 
	{
		return true;
	}

	return false;	
}


Rational Rational::operator++()
{
	this;
}
